﻿using System;
using System.Threading;
using System.Windows.Forms;
using ShevaEngine.Core.Modules.Graphics;
using ShevaEngine.Core.Modules.Graphics.Cameras;
using ShevaEngine2.Tools;
using ShevaEngineTools.Editor;


namespace ShevaEngineTools
{
    /// <summary>
    /// Graphics Viewport Control.
    /// </summary>
    public partial class GraphicsViewportControl : UserControl
    {
        /// <summary>Viewport.</summary>
        public GraphicsViewport Viewport;
        /// <summary>Draw mutex.</summary>
        public Mutex DrawMutex;
        /// <summary>Camera controller.</summary>
        public OrbitCameraController CameraController;
        /// <summary>Previous mouse position</summary>
        public System.Drawing.Point MousePosition;
        /// <summary>Gizmo.</summary>
        public Gizmo Gizmo;

        /// <summary>Mouse state changed event.</summary>
        public event OnMouseChangedCallBack MouseStateChanged;        

        /// <summary>
        /// Constructor.
        /// </summary>
        public GraphicsViewportControl()
        {
            this.DrawMutex = new Mutex();

            this.InitializeComponent();

            this.Viewport = new GraphicsViewport(new Microsoft.Xna.Framework.Rectangle(0, 0, this.Width, this.Height));            
        }

        /// <summary>
        /// On Load method.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void Init()
        {
            this.CameraController = new OrbitCameraController(this.Viewport.Camera);

            this.OnRender();
        }

        /// <summary>
        /// Methods OnRender.
        /// </summary>
        public void OnRender()
        {
            this.DrawMutex.WaitOne();

            this.Viewport.Renderer.CreateShadowMaps();

            ShevaEngine.Core.ShevaEngine.Instance.SpriteBatch.Begin();

            ShevaEngine.Core.ShevaEngine.Instance.SpriteBatch.Draw(
                this.Viewport.Draw(), new Microsoft.Xna.Framework.Rectangle(0, 0, this.Width, this.Height), Microsoft.Xna.Framework.Color.White);

            ShevaEngine.Core.ShevaEngine.Instance.SpriteBatch.End();
            
            Microsoft.Xna.Framework.Rectangle rectangle = new Microsoft.Xna.Framework.Rectangle(0, 0, this.Width, this.Height);

            ShevaEngine.Core.ShevaEngine.Instance.GraphicsDevice.Present(rectangle, rectangle, this.Handle);

            this.DrawMutex.ReleaseMutex();
        }

        /// <summary>
        /// Methods change resolution.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnResize(EventArgs e)
        {
            this.DrawMutex.WaitOne();

            base.OnResize(e);

            if (this.Viewport != null)
                this.Viewport.ResizeViewport(this.Width, this.Height);            

            this.DrawMutex.ReleaseMutex();
        }

        /// <summary>
        /// Mouse move.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GraphicsViewportControl_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)
                this.CameraController.Move(new Microsoft.Xna.Framework.Vector2(
                    e.Location.X - this.MousePosition.X, e.Location.Y - this.MousePosition.Y));

            if (e.Button == System.Windows.Forms.MouseButtons.Middle)
                this.CameraController.Rotate(new Microsoft.Xna.Framework.Vector2(
                    e.Location.X - this.MousePosition.X, e.Location.Y - this.MousePosition.Y));

            this.MousePosition = e.Location;
        }

        /// <summary>
        /// Mouse wheel.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseWheel(MouseEventArgs e)
        {
            base.OnMouseWheel(e);

            this.CameraController.Zoom(-e.Delta);
        }

        /// <summary>
        /// Settings button click.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            if (this.Viewport != null && this.Viewport.Renderer != null)
            {
                SettingsForm settingsForm = new SettingsForm(this.Viewport.Renderer);

                settingsForm.ShowDialog();
            }
        }                       
    }

    /// <summary>
    /// On mouse changed callback.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public delegate void OnMouseChangedCallBack(object sender, MouseEventArgs e);
}
